package edu.dhbw.andar.sample;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.ExecutionException;

import org.cocos2d.layers.CCScene;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.opengl.CCGLSurfaceView;

import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter.MalformedMimeTypeException;
import android.graphics.PixelFormat;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.util.Log;
import edu.dhbw.andar.ARToolkit;
import edu.dhbw.andar.AndARActivity;
import edu.dhbw.andar.exceptions.AndARException;
import edu.dhbw.andar.util.AssetsFileUtil;
import edu.dhbw.andar.util.BaseFileUtil;
import edu.dhbw.andar.util.CustomRenderer;
import edu.dhbw.andar.util.Model;
import edu.dhbw.andar.util.ObjParser;
import edu.dhbw.andar.util.ParseException;

/**
 * Example of an application that makes use of the AndAR toolkit.
 * @author Tobi
 *
 */
public class CustomActivity extends AndARActivity {

	private HashMap<String, Arbject> arbjects;
	private static HashMap<String, Model> models;
	private ARToolkit artoolkit;
    
    private NfcAdapter mAdapter;
    private PendingIntent pendingIntent;
    private IntentFilter ndef;
    
    private CCScene cocosScene;
    protected CCGLSurfaceView cocosView;
    
    //Could be used for specific RFID tech in future
//    private IntentFilter[] intentFiltersArray;
//    private String[][] techListsArray;

    @Override
	public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        cocosView = new CCGLSurfaceView(this);
        cocosView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
        cocosView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
        frame.addView(cocosView, 0);

        setupIntentFilter();
        
		CustomRenderer renderer = new CustomRenderer();//optional, may be set to null
		super.setNonARRenderer(renderer);//or might be omited
		
		artoolkit = super.getArtoolkit();
		arbjects = new HashMap<String, Arbject>();
		models = new HashMap<String, Model>();
		
		registerModels();
		
		startPreview();
    }
    
    private void registerModels(){
    	try {    		
    		BaseFileUtil fileUtil = new AssetsFileUtil(getResources().getAssets());
			fileUtil.setBaseFolder("models/");			

			ObjParser parser = new ObjParser(fileUtil);
			if(fileUtil != null){
				
				BufferedReader fileReader = fileUtil.getReaderFromName("bench.obj");
				Log.d("LOAD_MODEL", "Loading bench");
				models.put("bench", parser.parse("bench", fileReader));
				fileReader = fileUtil.getReaderFromName("superman.obj");
				Log.d("LOAD_MODEL", "Loading superman");
				models.put("superman", parser.parse("superman", fileReader));
				fileReader = fileUtil.getReaderFromName("sofa.obj");
				Log.d("LOAD_MODEL", "Loading sofa");
				models.put("sofa", parser.parse("sofa", fileReader));
//				fileReader = fileUtil.getReaderFromName("treasure_chest.obj");
//				Log.d("LOAD_MODEL", "Loading treasure_chest");
//				models.put("treasure_chest", parser.parse("treasure_chest", fileReader));
//				fileReader = fileUtil.getReaderFromName("plant.obj");
//				Log.d("LOAD_MODEL", "Loading plant");
//				models.put("plant", parser.parse("plant", fileReader));
				
				registerArbject("0c 10 ef 0f", "linda", "pattern1");
				registerArbject("ae e0 41 d2", "oleander", "pattern3");
				registerArbject("5e 6a 42 d2", "pokeylope", "pattern2");
				registerArbject("ee 0a 6d b7", "shield", "pattern_shield");
				registerArbject("de cf 3d d2", "lens", "pattern_lens");
				registerArbject("ee 42 39 d2", "harry", "pattern_harry");
			}
		} catch (AndARException ex){
			//handle the exception, that means: show the user what happened
			System.out.println("");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    public void registerArbject(String rfid, String patternName, String patternFile) throws AndARException{
    	arbjects.put(rfid, new Arbject(models.get("bench"), patternName, patternFile, rfid));
    	artoolkit.registerARObject(arbjects.get(rfid));
    }
    
    public void changeModel(String arbjectID, String value){   	
    	Arbject arbject = arbjects.get(arbjectID);
    	
    	if(value.equals("none")){
    		arbject.setModelToNone();
    	}
    	else {
    		arbject.changeModel(models.get(value), value);
    	}
    }
    
    public void setVisibility(String arbjectName, boolean isVisible){
    	arbjects.get(arbjectName).isVisible = isVisible;
    }
    
    public void setSharedData(String key, String value){
    	new Client().execute(key + " " + value);
    }
    
    public String getSharedData(String key) throws InterruptedException, ExecutionException{
    	return new Client().execute(key).get();
    }
    
    private void setupIntentFilter(){
    	mAdapter = NfcAdapter.getDefaultAdapter(this);
    	pendingIntent = PendingIntent.getActivity(
        	    this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
    	ndef = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        try {
            ndef.addDataType("*/*");    /* Handles all MIME based dispatches.
                                           You should specify only the ones that you need. */
        }catch (MalformedMimeTypeException e) {
            throw new RuntimeException("fail", e);
        }
//    	techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
//        intentFiltersArray = new IntentFilter[] {ndef, };
    }
    
    @Override
    public void onResume(){
    	CCDirector.sharedDirector().resume();
    	mAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
    	super.onResume();
    }
	
    @Override
    public void onStart(){
    	super.onStart();
    	CCDirector.sharedDirector().attachInView(cocosView);
        CCDirector.sharedDirector().setDisplayFPS(true);
        CCDirector.sharedDirector().setAnimationInterval(1.0f / 60.0f);
        cocosScene = GameLayer.scene();
        CCDirector.sharedDirector().runWithScene(cocosScene);
        ((GameLayer)(cocosScene.getChildren().get(0))).setARManager(this);
    }
    
    @Override
    public void onPause(){
    	CCDirector.sharedDirector().pause();
    	mAdapter.disableForegroundDispatch(this);
    	super.onPause();
    }
    
    @Override
    public void onStop(){
    	CCDirector.sharedDirector().end();
    	super.onStop();
    }
    
    @Override
    public void onNewIntent(Intent intent) {
    	super.onNewIntent(intent);
    	resolveIntent(intent);
    }
    
    private void resolveIntent(Intent intent) {
    	byte[] id = new byte[0];
        String action = intent.getAction();
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
            id = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
            ((GameLayer)(cocosScene.getChildren().get(0))).receiveNFC(getHex(id));
        }
    }

	private String getHex(byte[] bytes) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < bytes.length; i++) {
			int b = bytes[i] & 0xff;
			if (b < 0x10)
				sb.append('0');
			sb.append(Integer.toHexString(b));
			if (i != bytes.length - 1) {
				sb.append(" ");
			}
		}
		return sb.toString();
	}

    public void uncaughtException(Thread thread, Throwable ex) {
	// TODO Auto-generated method stub
	
	}
    
    public Arbject getArbject(String arbjectName){
    	return arbjects.get(arbjectName);
    }
    
    public HashMap<String, Arbject> getArbjects(){
    	return arbjects;
    }

    public Set<String> getArbjectKeys(){
    	return arbjects.keySet();
//    	return new ArrayList<String>(arbjects.keySet());
    }
    
    public static Model getModel(String modelID){
    	return models.get(modelID);
    }
}
